/* @flow */

import config from '../config'
import {initUse} from './use'
import {initMixin} from './mixin'
import {initExtend} from './extend'
import {initAssetRegisters} from './assets'
import {set, del} from '../observer/index'
import {ASSET_TYPES} from 'shared/constants'
import builtInComponents from '../components/index'
import {observe} from 'core/observer/index'

import {
  warn,
  extend,
  nextTick,
  mergeOptions,
  defineReactive
} from '../util/index'

/**
 * 2019-05-13
 * 1.在 Vue 构造函数上添加 config 属性
 */
export function initGlobalAPI(Vue: GlobalAPI) {
  // config
  const configDef = {}
  configDef.get = () => config
  if (process.env.NODE_ENV !== 'production') {
    configDef.set = () => {
      warn(
        'Do not replace the Vue.config object, set individual fields instead.'
      )
    }
  }
  Object.defineProperty(Vue, 'config', configDef);

  /**
   * 2019-05-13
   * Vue.util 以及 util 下的四个方法都不被认为是公共API的一部分
   * 在官方文档上也并没有介绍这个全局API，所以能不用尽量不要用
   */
  // exposed（暴露） util methods.
  // NOTE: these are not considered（被认为是） part of the public API - avoid（避免） relying（依赖） on
  // them unless（除非） you are aware（意识到） of the risk（风险）.
  Vue.util = {
    warn,
    extend,
    mergeOptions,
    defineReactive
  };

  Vue.set = set
  Vue.delete = del
  Vue.nextTick = nextTick

  /**
   * 2019-05-13
   * 暂时把下面这个代码改改，影响注释格式
   */
  // 2.6 explicit observable API
  // Vue.observable = <T>(obj: T): T => {
  //   observe(obj)
  //   return obj
  // };
  Vue.observable = (obj) => {
    observe(obj)
    return obj
  };

  /**
   * ----------------------------------------------------------------------------
   */
  Vue.options = Object.create(null);
  ASSET_TYPES.forEach(type => {
    Vue.options[type + 's'] = Object.create(null)
  });

  // this is used to identify the "base" constructor to extend all plain-object
  // components with in Weex's multi-instance scenarios.
  Vue.options._base = Vue
  /**
   * 2019-05-13
   * ----------------------------------------------------------------------------
   * 经过上面这个代码，Vue.options被赋值成如下：
   * Vue.options = {
   *    components: Object.create(null),
   *    directives: Object.create(null),
   *    filters: Object.create(null),
   *    _base: Vue
   * };
   */

  extend(Vue.options.components, builtInComponents)
  /**
   * 2019-05-13
   * 上面代码作用如下：
   * Vue.options.components = {
   *    KeepAlive
   * }
   */

  /**
   * 2019-05-13
   * 给Vue增加静态方法：use（用来安装 Vue 插件）
   */
  initUse(Vue)

  /**
   * 2019-05-13
   * 给Vue增加静态方法：mixin（猜测在组件中使用混入时候会有用处？？）
   */
  initMixin(Vue)

  initExtend(Vue)

  initAssetRegisters(Vue)
}
